﻿using Microsoft.Extensions.Logging;
using Quickuse.Logging.FileLogger;
using System;
using System.Collections.Generic;
using System.Text;

namespace Quickuse.Logging
{
    /// <summary>
    /// Logger
    /// </summary>
    internal class Logger : ILogger
    {

        /// <summary>
        /// LogCallback
        /// </summary>
        internal Action<string, LogLevel> LogCallback { get; set; }

        /// <summary>
        /// CategoryName
        /// </summary>
        public string CategoryName { get; set; }

        /// <summary>
        /// Filter
        /// </summary>
        public Func<string, LogLevel, bool> Filter { get; set; }

        /// <summary>
        /// 获得/设置 IExternalScopeProvider 实例
        /// </summary>
        public IExternalScopeProvider ScopeProvider { get; set; }

        /// <summary>
        /// Logger
        /// </summary>
        /// <param name="categoryName">categoryName</param>
        /// <param name="logCallback">logCallback</param>
        /// <param name="filter">filter</param>
        public Logger(string categoryName, Action<string, LogLevel> logCallback, Func<string, LogLevel, bool> filter = null)
        {
            CategoryName = categoryName;
            LogCallback = logCallback;
            Filter = filter ?? ((category, logLevel) => true);
        }

        /// <summary>
        /// BeginScope
        /// </summary>
        /// <typeparam name="TState">TState</typeparam>
        /// <param name="state">state</param>
        /// <returns></returns>
        public IDisposable BeginScope<TState>(TState state)
        {
            if (state == null)
            {
                throw new ArgumentNullException(nameof(state));
            }

            return LoggerScope.Push(CategoryName, state);
        }

        /// <summary>
        /// IsEnabled
        /// </summary>
        /// <param name="logLevel">logLevel</param>
        /// <returns></returns>
        public bool IsEnabled(LogLevel logLevel)
        {
            return Filter(CategoryName, logLevel);
        }

        /// <summary>
        /// Log
        /// </summary>
        /// <typeparam name="TState">TState</typeparam>
        /// <param name="logLevel">logLevel</param>
        /// <param name="eventId">eventId</param>
        /// <param name="state">state</param>
        /// <param name="exception">exception</param>
        /// <param name="formatter">formatter</param>
        public virtual void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
        {
            if (!IsEnabled(logLevel))
            {
                return;
            }

            var message = formatter.Invoke(state, exception);
            if (!string.IsNullOrEmpty(message) || exception != null)
            {
                LogCallback?.Invoke(message, logLevel);
            }
        }
    }
}
